/// \file RendererDX11.h
/// \date 2012-12-05
/// \brief concrete class that offers the rendering and graphics device related functionality in DX11

#ifndef _SNAKE_RENDER_RENDERERDX11_H__
#define _SNAKE_RENDER_RENDERERDX11_H__

// DirectX11
#include <d3d11.h>
#include <D3dx9math.h>
//#include <D3dx11core.h>

#include <Render/Include/Renderer.h>
#include <Render/Include/IWinWindow.h>

namespace Render
{

    /// \brief concrete class that offers the rendering and graphics device related functionality in DX11
    class RendererDX11 : public Renderer
    {
    public:
        // ========== LIFECYCLE ========== //

        /// \brief Constructor
        RendererDX11(IWinWindow* window);

        /// \brief Destructor
        virtual ~RendererDX11();

        // ========== OVERLODED OPERATORS ========== //

        // ========== METHODS ========== //

        /// \brief concrete method to render a scene
        virtual void renderScene(Model::Scene* scene);

        /// \brief concrete method to render black image
        virtual void renderBlack();

        // ========== GETTERS ========== //

        // ========== SETTERS ========== //

        // ========== INQUIRY ========== //

    private:
        /// \brief data to configure the constant buffer
        typedef struct
        {
            D3DXMATRIX world;
            D3DXMATRIX view;
            D3DXMATRIX projection;
            D3DXVECTOR4 color;
        }ConstantBufferData;

        /// \brief simple vertex description
        typedef struct
        {
            D3DXVECTOR3 position;
        }VertexData;
        // ========== INTERNAL METHODS ========== //

        /// \brief initializes a unitary cube
        void createCubeRenderObject();

        /// \brief initializes a unitary sphere
        void createSphereRenderObject();

        /// \brief configs the view point to do the rendering according to the scene
        void configViewPoint(Model::Scene* scene);

        /// \brief renders the scene walls
        void renderSceneWalls(Model::Scene* scene);

        /// \brief renders the snake head
        void renderSnakeHead(const Model::Element* &element);

        /// \brief renders the snake body element
        void renderSnakeBodyElement(const Model::Element* &element);

        /// \brief renders the text stored
        void drawText();

        /// \brief function used to compile a shader
        bool compileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut );

        // ========== ATTRIBUTES ========== //

        /// \brief directX11 device 
        ID3D11Device*  device;

        /// \brief directX11 immediate context 
        ID3D11DeviceContext* immediate_context;

        /// \brief directX11 swap chain 
        IDXGISwapChain* swap_chain;

        /// \brief directX11 render target
        ID3D11RenderTargetView* render_target_view;

        /// \brief directX11 depth stencil
        ID3D11DepthStencilView* depth_stencil_view;

        /// \brief directX11 viewport
        D3D11_VIEWPORT viewport;

        /// \brief directX11 vertex shader
        ID3D11VertexShader* vertex_shader;

        /// \brief directX11 pixel shader
        ID3D11PixelShader* pixel_shader;

        /// \brief directX11 vertex input layout
        ID3D11InputLayout* input_layout;

        /// \brief directX11 constant buffer pointer
        ID3D11Buffer* constant_buffer;

        /// \brief directX11 constant buffer data
        ConstantBufferData constant_buffer_data;
    };
};
#endif // _SNAKE_RENDER_RENDERERDX11_H__
